#include "kernel.h"
#include  "global.h"
#include <stdio.h>

MsgEnvQ::MsgEnvQ(int NumOfNodes){
    head=tail=0;
    size=0;
    if (NumOfNodes>0){
        MsgEnv *cur;
        cur=new MsgEnv;
        head=tail=cur;
        cur->next=0;
            size++;
        while (size<NumOfNodes){
            cur=new MsgEnv;
            tail->next=cur;
            tail=cur;
            cur->next=0;
            size++; 
        }
    }    
}

void MsgEnvQ::enqueue(MsgEnv * newNode){
         if (size==0)
         {head=newNode;tail=newNode;size++;return;}
         tail->next=newNode;
         tail=newNode;	  
         newNode->next=0;
        size++;
        //cout << "enqueue!";
        return;
}

int MsgEnvQ::sorted_enqueue(MsgEnv * newNode){
MsgEnv* cur=timeout_list->head;
    while (head!=NULL){
             if (timeout_list->size()==1){;//if only 1 node
                       if (newNode->num_clock_ticks>=timeout_list->head->num_clock_ticks){//code to sort the envelope into the timeout_list
                                newNode->next=cur;
                                head=newNode;
                                timeout_list.size()++;
                       return 1;
                       };
                       else if (newNode->num_clock_ticks<=time_list->head->num_clock_ticks){
                                cur->next=newNode;
                                timeout_list->tail=newNode;
                                timeout_list.size()++;
                       return 1;
                       };
             else{//more than 1 node
                       MsgEnv* A=timeout_list->head;
                       MsgEnv* B=timeout_list->head->next;
                       if (newNode->num_clock_ticks>=A->num_clock_ticks){//case 1:newnode is greater than first node, so it becomes the new node
                                newNode->next=A;
                                head=newNode;
                                timeout_list.size()++;
                                return 1;
                       }
                       if{newNode->num_clock_tick<timeout_list->tail->num_clock_tick){//case 2: newnode is SMALLER THAN LAST NODE, so it becomes the new tail
                                Msg* temp;
                                temp=timeout_list->tail;
                                temp->next=newNode;
                                timeout_list->tail=newNode;
                       };
                       if (newNode->num_clock_ticks > timeout_list->head->clockticks && msg_env->clockticks < timeout_Q->tail->clockticks){//case 3:its in the middle, traverse until it fits
                                while(a->next!=NULL){
                                      if(newNode->num_clock_ticks < A->num_clock_ticks && msg_env->clockticks > B->num_clock_ticks){
                                           newNode->next=A;
                                           head=newNode;
                                           timeout_list.size()++;
                                           return 1;
                                      };
                                      else{
                                           A=A->next;
                                           B=B->next;
                                      };
                                };
                       };
        };
};                                
                                
MsgEnv * MsgEnvQ::dequeue(){
	MsgEnv * temp;
	if (this->size == 0|| this->head==0){
		//cout << "its empty !";
		return 0;
	}		
	temp=head;
	head=temp->next;
	temp->next=0;
	size--;
	//cout << "dequeue!";
	return temp;
}

int MsgEnvQ::getsize(){//count number of nodes in the queue
		return size;
}


void PCBQ::enqueue(PCB * newNode){
         if (size==0)
         {head=newNode;tail=newNode;size++;return;}
         tail->next=newNode;
         tail=newNode;	  
         newNode->next=0;
        size++;
        //cout << "enqueue!";
        return;
}

PCB * PCBQ::dequeue(){
	PCB * temp;
	if (this->size == 0|| this->head==0){
		//cout << "its empty !";
		return 0;
	}		
	temp=head;
	head=temp->next;
	temp->next=0;
	size--;
	//cout << "dequeue!";
	return temp;
}

int PCBQ::getsize(){//count number of nodes in the queue
		return size;
}

void timeout_iproc(){
     MsgEnv* temp;
     temp=timeout_iproc().receive_message();
     sorted_enqueue(temp);
    }
	if (timeout_list->head=!NULL){	
           temp=timeout_list->head; 
            while(temp!=NULL){
                temp->num_clock_ticks--;
                temp=temp->next;
        }
		//code to decrement the tick count of 1st in the timeout_list
		while(timeout_list->tail->num_clock_ticks==0){
			MsgEnv* temp;
                        temp=timeout_list->dequeue();
                        int target_ID=temp->sender_pid;
			send_message(target_ID, temp); //returns envelope
		};
	};
};



/*
//Class Queue
template <class nodeType>
Queue<nodeType>::Queue(int NumOfNodes){
    head=tail=NULL;
    size=0;
    nodeType *temp;
    while (size<NumOfNodes){
        temp=new nodeType();
        this->enqueue(temp);
        temp=NULL;
    }
}
template <class nodeType>
Queue<nodeType>::~Queue(){
		//free all the nodes and then destroy the queue	
    delete [] head, tail, size;
}

template <class nodeType>
void Queue<nodeType>::enqueue(nodeType * newNode){
	 if (size<1)
	 {head=newNode;tail=newNode;size++;return;}
	 tail->next=newNode;
	 tail=newNode;	  
	 newNode->next=NULL;
        size++;
        //cout << "enqueue!";
        return;
}

template <class nodeType>
nodeType * Queue<nodeType>::dequeue(){
	node * temp;
	if (this->size == 0|| this->head==NULL){
		//cout << "its empty !";
		return NULL;
	}		
	temp=head;
	head=temp->next;
	temp->next=NULL;
	size--;
	//cout << "dequeue!";
	return temp;
}

template <class nodeType>
int Queue<nodeType>::getsize(){//count number of nodes in the queue
		return size;
}

template <class nodeType>
int Queue<nodeType>::empty(){
		if (size==0)
			 return 1;
		else
			 return 0;
}
*/
/*
//Class Stack

Stack::Stack(int size){
return -1;					  
}

Stack::~Stack(){
return -1;						  
}
int * Stack::pop(){
return -1;	
}
void Stack::push(int * item){
}

BlockedQ();
				 ~BlockedQ();
				 //return total number of blocked PCBs
				 int getSize();
				 //return total number of PCBs in the selected type queue
				 int getSize(int priority);
				 void enqueue(PCB * newpcb, int blockedType);
				 PCB * dequeue(int blockedtype);
				 int empty();
*/















